#ifndef DEVICEMANAGER_H
#define DEVICEMANAGER_H

#include <QObject>
#include <QVector>
#include <QMap>
#include <QTimer>
#include <QMutex>
#include "meter.h"
#include "../io/serialportmanager.h"
#include "../io/pollscheduler.h"

/**
 * @brief 设备管理器类
 * 管理120块电表的注册、状态和数据更新
 * 提供自动拓扑识别和在线/离线检测功能
 */
class DeviceManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged)
    Q_PROPERTY(int onlineCount READ onlineCount NOTIFY onlineCountChanged)
    Q_PROPERTY(int offlineCount READ offlineCount NOTIFY offlineCountChanged)
    Q_PROPERTY(bool scanning READ isScanning NOTIFY scanningChanged)

public:
    /**
     * @brief 总线配置结构
     */
    struct BusConfig
    {
        int busId;        ///< 总线ID（1-3）
        QString busName;  ///< 总线名称
        QString portName; ///< 串口名称
        int startSlaveId; ///< 起始站号
        int endSlaveId;   ///< 结束站号
    };

    explicit DeviceManager(SerialPortManager *portManager, QObject *parent = nullptr);
    ~DeviceManager();

    /**
     * @brief 添加总线配置
     * @param config 总线配置
     * @return 是否添加成功
     */
    bool addBusConfig(const BusConfig &config);

    /**
     * @brief 添加总线配置（QML友好）
     * @param busId 总线ID（1-3）
     * @param busName 总线名称
     * @param portName 串口名称
     * @param startSlaveId 起始站号
     * @param endSlaveId 结束站号
     * @return 是否添加成功
     */
    Q_INVOKABLE bool addBusConfigQml(int busId, const QString &busName, const QString &portName, int startSlaveId, int endSlaveId);

    /**
     * @brief 清空所有总线配置（QML友好）
     */
    Q_INVOKABLE void clearBusConfigs();

    /**
     * @brief 启动自动拓扑识别（QML友好）
     * 扫描所有配置的站号，识别在线设备
     * @param timeout 每个站号的超时时间（毫秒）
     */
    Q_INVOKABLE void startTopologyDiscovery(int timeout = 500);

    /**
     * @brief 停止拓扑识别（QML友好）
     */
    Q_INVOKABLE void stopTopologyDiscovery();

    /**
     * @brief 启动轮询（在拓扑识别完成后调用）（QML友好）
     * @param pollInterval 轮询间隔（毫秒）
     * @return 是否成功启动
     */
    Q_INVOKABLE bool startPolling(int pollInterval = 500);

    /**
     * @brief 停止轮询（QML友好）
     */
    Q_INVOKABLE void stopPolling();

    /**
     * @brief 启动在线状态监测（QML友好）
     * @param checkInterval 检查间隔（毫秒），默认5秒
     * @param timeoutSeconds 超时时间（秒），默认10秒
     */
    Q_INVOKABLE void startOnlineMonitor(int checkInterval = 5000, int timeoutSeconds = 10);

    /**
     * @brief 停止在线状态监测（QML友好）
     */
    Q_INVOKABLE void stopOnlineMonitor();

    /**
     * @brief 将所有电表设置为离线状态（用于系统停止时清理状态）
     */
    void setAllMetersOffline();

    /**
     * @brief 获取总线配置数量（QML友好）
     * @return 总线配置数量
     */
    Q_INVOKABLE int busConfigCount() const { return m_busConfigs.size(); }

    /**
     * @brief 获取所有电表
     * @return 电表列表
     */
    QVector<Meter *> getAllMeters() const;

    /**
     * @brief 根据ID获取电表
     * @param meterId 电表ID（站号）
     * @return 电表对象指针，如果不存在返回nullptr
     */
    Meter *getMeter(int meterId) const;

    /**
     * @brief 根据总线ID获取电表列表
     * @param busId 总线ID
     * @return 该总线上的电表列表
     */
    QVector<Meter *> getMetersByBus(int busId) const;

    /**
     * @brief 获取在线电表列表
     * @return 在线电表列表
     */
    QVector<Meter *> getOnlineMeters() const;

    /**
     * @brief 获取电表总数
     */
    int totalCount() const { return m_meters.size(); }

    /**
     * @brief 获取在线电表数量
     */
    int onlineCount() const;

    /**
     * @brief 获取离线电表数量
     */
    int offlineCount() const;

    /**
     * @brief 是否正在扫描
     */
    bool isScanning() const { return m_scanning; }

    /**
     * @brief 获取指定总线的在线电表数量（QML友好）
     * @param busId 总线ID
     * @return 在线电表数量
     */
    Q_INVOKABLE int getOnlineCountByBus(int busId) const;

    /**
     * @brief 获取指定总线的总功率（QML友好）
     * @param busId 总线ID
     * @return 总功率（W）
     */
    Q_INVOKABLE double getTotalPowerByBus(int busId) const;

    /**
     * @brief 获取指定总线的总电流（QML友好）
     * @param busId 总线ID
     * @return 总电流（A）
     */
    Q_INVOKABLE double getTotalCurrentByBus(int busId) const;

signals:
    /**
     * @brief 拓扑识别开始信号
     */
    void topologyDiscoveryStarted();

    /**
     * @brief 拓扑识别完成信号
     * @param totalFound 发现的电表数量
     */
    void topologyDiscoveryCompleted(int totalFound);

    /**
     * @brief 拓扑识别进度信号
     * @param current 当前扫描的站号
     * @param total 总站号数
     */
    void topologyDiscoveryProgress(int current, int total);

    /**
     * @brief 发现新设备信号
     * @param meterId 电表ID
     */
    void deviceDiscovered(int meterId);

    /**
     * @brief 设备上线信号
     * @param meterId 电表ID
     */
    void deviceOnline(int meterId);

    /**
     * @brief 设备离线信号
     * @param meterId 电表ID
     */
    void deviceOffline(int meterId);

    /**
     * @brief 电表总数改变信号
     */
    void totalCountChanged();

    /**
     * @brief 在线电表数量改变信号
     */
    void onlineCountChanged();

    /**
     * @brief 离线电表数量改变信号
     */
    void offlineCountChanged();

    /**
     * @brief 扫描状态改变信号
     */
    void scanningChanged();

    /**
     * @brief 电表数据批量更新信号（用于UI刷新优化）
     * @param meterIds 已更新的电表ID列表
     */
    void meterDataBatchUpdated(const QVector<int> &meterIds);

    /**
     * @brief 电表数据采样信号（用于数据存储）
     * @param meterId 电表ID
     * @param meter 电表对象指针
     */
    void meterDataSampled(int meterId, Meter *meter);

private slots:
    /**
     * @brief 执行拓扑识别
     */
    void performTopologyDiscovery();

    /**
     * @brief 检查在线状态
     */
    void checkOnlineStatus();

    /**
     * @brief 处理电表上线/离线状态变化
     */
    void onMeterOnlineChanged();

private:
    /**
     * @brief 创建电表对象
     * @param meterId 电表ID
     * @param busId 总线ID
     * @param busName 总线名称
     * @return 电表对象指针
     */
    Meter *createMeter(int meterId, int busId, const QString &busName);

    SerialPortManager *m_portManager; ///< 串口管理器
    PollScheduler *m_pollScheduler;   ///< 轮询调度器

    QMap<int, Meter *> m_meters;     ///< 电表映射（key: meterId）
    QVector<BusConfig> m_busConfigs; ///< 总线配置列表

    QTimer *m_discoveryTimer;     ///< 拓扑识别定时器
    QTimer *m_onlineMonitorTimer; ///< 在线监测定时器

    bool m_scanning;                  ///< 是否正在扫描
    int m_discoveryTimeout;           ///< 拓扑识别超时时间
    int m_discoveryCurrentIndex;      ///< 当前扫描索引
    QVector<int> m_discoverySlaveIds; ///< 待扫描的站号列表

    int m_onlineCheckTimeout; ///< 在线检测超时时间（秒）

    mutable QMutex m_metersMutex; ///< 电表映射访问互斥锁
};

#endif // DEVICEMANAGER_H
